import { compareTwoVdom, findDOM } from "./react-dom";

export const updateQueue = {
    isBatchingUpdate: false, // 控制更新是同步还是异步
    updateres: [], // 需要更新的那些
    batchUpdate() { // 批量更新
        // 发布开始更新
        updateQueue.updateres.forEach(updater => updater.updateComponent());
        updateQueue.isBatchingUpdate = false;
        updateQueue.updateres.length = 0;
    }
}

class Updater {
    constructor(classInstance) {
        this.classInstance = classInstance;
        this.pendingStates = [];
        this.callbacks = [];
    }

    addState(partialState, callback) {
        this.pendingStates.push(partialState);///等待更新的或者说等待生效的状态
        if (typeof callback === 'function') {
            this.callbacks.push(callback);//状态更新后的回调
        }
        this.emitUpdate();  
    }

    emitUpdate(newProps) {
        this.nextProps = newProps;
        if (updateQueue.isBatchingUpdate) { // 批量更新, 先订阅保存
            updateQueue.updateres.push(this);
        } else {
            this.updateComponent();
        }
    }

    updateComponent() {
        // 属性或者和状态更新
        if (this.nextProps || this.pendingStates.length > 0) {
            this.shouldUpdate(this.classInstance, this.nextProps, this.getState());
        }
    }

    getState() {
        const { classInstance, pendingStates } = this;
        let { state } = classInstance; // 旧的状态
        pendingStates.forEach(nextState => {
            if (typeof nextState === 'function') {
                // setState可能是传一个函数
                nextState = nextState(state);
            }
            state = { ...state, ...nextState };
        })

        pendingStates.length = 0; // 清空
        return state;
    }

    shouldUpdate(classInstance, nextProps, nextState) {
        let willUpdate = true;
        if (classInstance.shouldComponentUpdate && !classInstance.shouldComponentUpdate(nextProps, nextState)) {
            // 是否更新继续渲染视图
            willUpdate = false;
        }
        if (willUpdate && classInstance.componentWillUpdate) {
            classInstance.componentWillUpdate(); // 执行用户的钩子函数
        }
        if (nextProps) {
            classInstance.props = nextProps;
        }
        classInstance.state = nextState; // 更新状态
        if (willUpdate) {
            classInstance.forceUpdate(); // 更新
        }
    }
}

class Component {

    // isReactComponent 表示是类组件
    static isReactComponent = true;
    constructor(props) {
        this.props = props;
        this.state = {};
        this.updater = new Updater(this)
    }

    setState(partialState, callback) {
        this.updater.addState(partialState, callback);
    }

    // 更新视图
    forceUpdate() {
        const oldRenderVdom = this.oldRenderVdom;// 获取老的虚拟DOM
        // const oldDOM = findDOM(oldRenderVdom); // 获取老的真实DOM
        const oldDOM = findDOM(oldRenderVdom);
        const newRenderVdom = this.render(); // 执行组件中的 render 函数
        
        // dom diff
        compareTwoVdom (oldDOM.parentNode, oldRenderVdom, newRenderVdom);
        
        this.oldRenderVdom = newRenderVdom;
        if (this.componentDidUpdate) {
            this.componentDidUpdate(this.props, this.state); // 执行用户的钩子函数 
        }
    }
}

export {
    Component
};